module numeric_grid; 
use memory;
use vec;
implicit none;
logical, save :: GRID_MOD_TRACE_ENTRY = .TRUE.;

contains 

SUBROUTINE numeric_grid_test();  implicit none; 
  call dbg_info("-->numeric_grid_test()"); 
  call step_grid_test();
  !ok = vec_dot_test_speed();
end SUBROUTINE


! TODO: 13-Mar-2013
SUBROUTINE step_grid_test();  implicit none; 
  integer :: nv;
  real(R14) :: minv, maxv;  
  real(R14), dimension(:), pointer :: pv;        
  call dbg_info("-->step_grid_test()"); 
  call dbg_vec_all_on();

  nv = 2;  minv = 0.; maxv = 1.;
  pv => new_vec(nv);  
  call calc_step_grid(pv, 1, nv, minv, maxv);
  call assert_max_zero("2.pv(1)=minv", pv(1) - minv);
  call assert_max_zero("2.pv(nv)=maxv", pv(nv) - maxv);
  call del_vec(pv);

  nv = 3;  minv = -1.; maxv = 1.;
  pv => new_vec(nv);  
  call calc_step_grid(pv, 1, nv, minv, maxv);
  call assert_max_zero("3.pv(1)=minv", pv(1) - minv);
  call assert_max_zero("3.pv(2)=0", pv(2));
  call assert_max_zero("3.pv(nv)=maxv", pv(nv) - maxv);
  call del_vec(pv);
  call del_vec(pv);
end SUBROUTINE

SUBROUTINE calc_step_grid(v, mini, maxi, vmin, vmax);    implicit none;  
  real(R14), dimension(:) :: v;      
  integer, intent(in) :: mini, maxi;
  real(R14), intent(in) :: vmin, vmax; ! v1-first value; v2-last value
  real(R14) step;   integer :: i, nv; ! num of point in v
  call dbg_info("-->calc_step_grid()", GRID_MOD_TRACE_ENTRY);
  nv = maxi - mini + 1;
  call assert_true("(nv > 0)=", nv > 1);
  step = (vmax - vmin) / real(nv-1);
  v(mini) = vmin;
  do i = mini + 1, maxi
    v(i) = v(i-1) + step;
  end do
end SUBROUTINE

SUBROUTINE calc_step_grid3(v, vmin, vmax);    implicit none;
  type(VEC_T) :: v;
  real(R14), intent(IN) :: vmin, vmax; ! v1-first value; v2-last value
  real(R14) step;   integer :: i, nv; ! num of point in v
  call dbg_info("-->calc_step_grid()", GRID_MOD_TRACE_ENTRY);
  nv = v%maxi - v%mini + 1;
  call assert_true("(nv > 0)=", nv > 1);
  step = (vmax - vmin) / real(nv-1);
  v%p(v%mini) = vmin;
  do i = v%mini + 1, v%maxi
    v%p(i) = v%p(i-1) + step;
  end do
end SUBROUTINE

! only checks two intervals at the front and two at the back
SUBROUTINE assert_step_grid_4(px);    implicit none;  
  real(R14), intent(IN) :: px(:);      
  real(R14) st, st2;
  integer xn, mini, maxi;
  xn = SIZE(px, 1);  mini = LBOUND(px, 1); maxi = UBOUND(px, 1);
  call assert_true("xn >= 3", xn >= 3); ! pointless if < 3
  call assert_true("px(mini+1)>px(mini)", px(mini+1)>px(mini));
  call assert_true("px(maxi)>px(maxi-1)", px(maxi)>px(maxi-1));
  
  st = px(mini + 1) - px(mini);
  st2 = px(mini + 2) - px(mini + 1);
  call assert_max_diff("mini", st, st2, ERR14);
  st = px(maxi) - px(maxi - 1);
  call assert_max_diff("mini,maxi", st, st2, ERR14);
  st2 = px(maxi - 1) - px(maxi - 2);
  call assert_max_diff("maxi", st, st2, ERR14);
end SUBROUTINE

end module 
